package com.mars.portal.web.common;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.dubbo.rpc.RpcException;
import com.alibaba.fastjson.JSON;
import com.mars.common.exception.BizException;
import com.mars.common.page.PageParam;
import com.mars.common.utils.CommonUtils;
import com.mars.common.utils.WebUtil;
import com.mars.web.common.support.SupperController;

/**
 * 基础控制类
 * 
 * @author 杨浩泉
 * @version 2016年10月14日
 */
public class BaseController extends SupperController implements HandlerInterceptor {
	
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		return true;
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
	}
	
	/**
	 * 获取分页参数，包含当前页、每页记录数.
	 * @return
	 */
	public PageParam getPageParam() {
		return new PageParam(getPageNum(), getNumPerPage(), getOrderBy()) ;
	}

	/**
	 * 当前页数
	 * @return
	 */
	private int getPageNum() {
		String pageNumStr = request.getParameter("page");
		int pageNum = 1;
		if (StringUtils.isNotBlank(pageNumStr)) {
			pageNum = Integer.valueOf(pageNumStr);
		}
		return pageNum;
	}
	
	/**
	 * 获取每页记录数
	 * 如果没有值则默认返回20.
	 * @return
	 */
	private int getNumPerPage() {
		String numPerPageStr = request.getParameter("rows");
		int numPerPage = 20;
		if (StringUtils.isNotBlank(numPerPageStr)) {
			numPerPage = Integer.parseInt(numPerPageStr);
		}
		return numPerPage;
	}

	/**
	 * 查询排序
	 * @return
	 */
	private String getOrderBy() {
		String sort = request.getParameter("sort");
		String order = request.getParameter("order");
		if (CommonUtils.isNotEmpty(sort)) {
			return sort + " " + (CommonUtils.isNotEmpty(sort) ? order : "DESC") ;
		}
		return null ;
	}
	
	/**
	 * 统一异常处理
	 * @param e
	 * @param request
	 * @param response
	 * @return
	 */
	@ExceptionHandler(Exception.class)
    public ModelAndView handleException(Exception e, HttpServletRequest request, HttpServletResponse response){
    	String requestType = request.getHeader("X-Requested-With");
    	Map<String, Object> map = new HashMap<String, Object>() ;
    	
		if(!"XMLHttpRequest".equals(requestType)) {//非Ajax请求
			ModelAndView mv = new ModelAndView();
			map.put("request", WebUtil.getCurrentUrl(request, true)) ;
			
			if(e instanceof BizException) {
				mv.setViewName("exception/500");
				mv.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
				map.put("status", mv.getStatus().value()) ;
				map.put("message", e.getMessage()) ;
				mv.addAllObjects(map) ;
			} else if(e instanceof RpcException){
				mv.setViewName("exception/500");
				mv.setStatus(HttpStatus.SERVICE_UNAVAILABLE);
				map.put("status", mv.getStatus().value()) ;
				map.put("message", "Dubbo分布式服务不可用<br>"+e.getMessage()) ;
				
				mv.addAllObjects(map) ;
	    	} else {
				mv.setViewName("exception/500");
				mv.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
				map.put("status", mv.getStatus().value()) ;
				map.put("message", e.getMessage()) ;
				mv.addAllObjects(map) ;
			}
	    	return mv;
	    	
		} else {
			response.setContentType("application/json;charset=utf-8");
			PrintWriter out = null ;
			try {
				out = response.getWriter() ;
				if(e instanceof BizException){
					response.setStatus(500);
					map.put("status", response.getStatus()) ;
					map.put("message", e.getMessage()) ;
					map.put("request", WebUtil.getCurrentUrl(request, true)) ;
					out.print(JSON.toJSONString(map));
		    	} else if(e instanceof RpcException){
					response.setStatus(503);
					map.put("status", response.getStatus()) ;
					map.put("message", "Dubbo分布式服务不可用<br>"+e.getMessage()) ;
					map.put("request", WebUtil.getCurrentUrl(request, true)) ;
					out.print(JSON.toJSONString(map));
		    	} else {
		    		response.setStatus(500);
					map.put("status", response.getStatus()) ;
					map.put("message", e.getMessage()) ;
					map.put("request", WebUtil.getCurrentUrl(request, true)) ;
					out.print(JSON.toJSONString(map));
		    	}
				
			} catch (IOException ioEx) {
				ioEx.printStackTrace();
			} finally{
				out.flush();
				out.close();
			}
			return null;
		}
	}

}
